﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace IOP.Extension
{
    /// <summary>
    /// 通用泛型比较器
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <typeparam name="C"></typeparam>
    public class Compare<T, C> : IEqualityComparer<T>
    {
        private Func<T, C> _getField;
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="getfield"></param>
        public Compare(Func<T, C> getfield)
        {
            _getField = getfield;
        }
        /// <summary>
        /// 比较
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        public bool Equals(T x, T y)
        {
            return EqualityComparer<C>.Default.Equals(_getField(x), _getField(y));
        }
        /// <summary>
        /// 获取哈希值
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public int GetHashCode(T obj)
        {
            return EqualityComparer<C>.Default.GetHashCode(_getField(obj));
        }
    }

    /// <summary>
    /// 扩展
    /// </summary>
    public static class EqualityComparerExtensions
    {
        /// <summary>
        /// 根据特定字段去重
        /// </summary>
        /// <typeparam name="T">要去重的对象类</typeparam>
        /// <typeparam name="C">自定义去重的字段类型</typeparam>
        /// <param name="source">要去重的对象</param>
        /// <param name="getfield">获取自定义去重字段的委托</param>
        /// <returns></returns>
        public static IEnumerable<T> ToDistinct<T, C>(this IEnumerable<T> source, Func<T, C> getfield)
            where C : IComparable<C>
        {
            return source.Distinct(new Compare<T, C>(getfield));
        }

        /// <summary>
        /// 根据特定字段求交集
        /// </summary>
        /// <typeparam name="T">要求交集的对象类</typeparam>
        /// <typeparam name="C">自定义求交集的字段类型</typeparam>
        /// <param name="first">源数据</param>
        /// <param name="second">要求交集的第二个集合</param>
        /// <param name="getfield">自定义字段委托</param>
        /// <returns></returns>
        public static IEnumerable<T> ToIntersect<T, C>(this IEnumerable<T> first, IEnumerable<T> second, Func<T, C> getfield)
            where C : IComparable<C>
        {
            return first.Intersect(second, new Compare<T, C>(getfield));
        }
    }
}
